package com.hxht.storage.server.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hxht.storage.server.bean.ManualRecordBean;
import com.hxht.storage.server.bean.RecordMarkBean;
import com.hxht.storage.server.bean.RecordSearchBean;
import com.hxht.storage.server.bean.RecordSearchDeviceInfoBean;
import com.hxht.storage.server.bean.RecordSearchResultBean;
import com.hxht.storage.server.bean.RecordStopBean;
import com.hxht.storage.server.bean.TimeIntersection;
import com.hxht.storage.server.dao.DeviceChannelDao;
import com.hxht.storage.server.dao.ManualRecordDao;
import com.hxht.storage.server.pojo.NvrDeviceInfo;
import com.hxht.storage.server.pojo.NvrIpchannelInfo;
import com.hxht.storage.server.pojo.RecordMarkInfo;
import com.hxht.storage.server.pojo.VideoDeviceChannelInfo;
import com.hxht.storage.server.pojo.VideoManualRecord;
import com.hxht.storage.server.service.ManualRecordService;
import com.hxht.storage.server.service.NvrDeviceService;
import com.hxht.storage.server.service.PlanRecordService;
import com.hxht.storage.server.service.SchedulerService;
import com.hxht.storage.server.util.NvrBeanTransUtil;

@Service
public class ManualRecordServiceImpl implements ManualRecordService {

	private static final Logger LOG = Logger.getLogger(ManualRecordServiceImpl.class);
	
	@Autowired
	private NvrDeviceService dvrService;

	@Autowired
	private SchedulerService schedulerService;
	
	@Autowired
	private ManualRecordDao manualRecordDao;
	
	@Autowired
	private DeviceChannelDao deviceChannelDao;
	
	@Autowired
	private PlanRecordService planRecordService;
	
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	@Override
	public String startRecord(ManualRecordBean manualRecordBean) {

		// 查询该device的 channel， 是否正在录像
		// 若正在录像，直接返回成功
		VideoManualRecord recording = manualRecordDao.getRecodingDevice(manualRecordBean.getDeviceId(),
				manualRecordBean.getDeviceChannelIndex());
		
		if (recording != null){
			LOG.info(" device is already recording!");
			LOG.info("---deviceId--------:" + manualRecordBean.getDeviceId());
			LOG.info("---deviceChannel---:" + manualRecordBean.getDeviceChannelIndex());
			
			return recording.getUuid();
		}
		
		VideoManualRecord record = null;

		// 查询该device的channel,是否正在计划录像
		boolean isPlanRecording = planRecordService.isRecording(manualRecordBean.getDeviceId(),
				manualRecordBean.getDeviceChannelIndex());
		
		if (isPlanRecording){
			// 若正在计划录像，则使用该计划录像的 ip通道进行手工录像
			NvrIpchannelInfo ipchannel = planRecordService.getRecordingIpchannel(manualRecordBean.getDeviceId(),
					manualRecordBean.getDeviceChannelIndex());
			record = dvrService.startManualRecord(manualRecordBean, ipchannel.getNvrDevice().getIp(), 
					ipchannel.getDvrChannel());
		} else {
			// 若当前没有进行计划录像，则选择一个nvr ip通道进行手工录像
			// 调用dvrService去进行 dvr.dll的jni调用，让nvr进行手工录像
			// record 返回的录像数据
			record = dvrService.startManualRecord(manualRecordBean);
		}

		// record为 null,说明 jni 调用nvr进行手工录像失败
		if (record == null) {
			return "";
		}
		
		manualRecordDao.insert(record);
		
		// recordDuration,表示 录像时长，为0，表示不用定时关闭
		// 已存在计划录像时，手工录像停止时，不删除ip通道，通过 !isPlanRecording 控制
		if (manualRecordBean.getRecordDuration() != 0){
			schedulerService.scheduleStopRecordJob(record.getIpChannel().getNvrDevice().getDeviceId(), 
					record.getIpChannel().getNvrChannel(), !isPlanRecording, manualRecordBean.getRecordDuration());
		}
		return record.getUuid();
	}

	@Override
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	public boolean stopRecord(RecordStopBean recordStopBean) {

		VideoManualRecord recording = manualRecordDao.getRecodingDevice(
				recordStopBean.getVideoDeviceId(),
				recordStopBean.getVideoDeviceChannelIndex());

		if (recording == null) {
			return false;
		}
		
		boolean stopResult = false;
		// 查找当前是否进行 计划录像
		boolean isPlanRecording = planRecordService.isRecording(recordStopBean.getVideoDeviceId(),
				recordStopBean.getVideoDeviceChannelIndex());
		if (isPlanRecording){
			// 若正在计划录像，则直接停止手工录像，不解除通道绑定
			stopResult = dvrService.stopManualRecord(recording, false);
		} else {
			// 若当前未计划录像，则停止手工录像，并解除通道绑定
			stopResult = dvrService.stopManualRecord(recording, true);
		}

		if (!stopResult) {
			return false;
		}

		manualRecordDao.update(recording);
		return true;
	}

	public NvrDeviceService getDvrService() {
		return dvrService;
	}

	public void setDvrService(NvrDeviceService dvrService) {
		this.dvrService = dvrService;
	}

	public ManualRecordDao getManualRecordDao() {
		return manualRecordDao;
	}

	public void setManualRecordDao(ManualRecordDao manualRecordDao) {
		this.manualRecordDao = manualRecordDao;
	}

	@Override
	public List<RecordSearchResultBean> searchRecordByDevice(
			RecordSearchBean searchBean, List<Integer> types) {

		LOG.info("search manual record is beginning---------------");
//		LOG.info("---deviceId 	  : " + searchBean.getVideoDeviceId() + "---");
//		LOG.info("---channelIndex	  : " + searchBean.getVideoDeviceChannelIndex() + "---");
		
		List<RecordSearchResultBean> resultBeanList = new ArrayList<RecordSearchResultBean>();
		
		List<VideoManualRecord> recordList = getRecordList(searchBean, types);
		
		Map<String, RecordSearchResultBean> resultMap = new HashMap<String, RecordSearchResultBean>();
		
		if (recordList != null && recordList.size() != 0){
			for (VideoManualRecord record : recordList){
				NvrDeviceInfo nvr = record.getIpChannel().getNvrDevice();
				String nvrIp = nvr.getIp();
				int ipchannelIndex = record.getIpChannel().getNvrChannel();
				RecordSearchResultBean tempBean = resultMap.get(nvrIp + "_" + ipchannelIndex);
				if (tempBean == null){
					tempBean = new RecordSearchResultBean();
					tempBean.setIp(nvrIp);
					tempBean.setPort(nvr.getPort());
					tempBean.setUsername(nvr.getUsername());
					tempBean.setPasswd(nvr.getPasswd());
					tempBean.setIpchannel(ipchannelIndex);
					resultMap.put(nvrIp + "_" + ipchannelIndex, tempBean);
					resultBeanList.add(tempBean);
				}
				
				// 若record的 停止时间为null,表示record正在录像，则设置当前nvr时间为停止时间
				Date stop = dvrService.getCurrentNvrTime(nvrIp);
				if (record.getStopTime() != null)
					stop = record.getStopTime();
				
				List<RecordMarkBean> markBeans = new ArrayList<RecordMarkBean>();
				
				for (RecordMarkInfo mark:record.getRecordMarks()){
					markBeans.add(NvrBeanTransUtil.transMarkInfoToMarkBean(mark));
				}
				tempBean.addTimePeriod(record.getDeviceId(), record.getDeviceChannel(),
						record.getStartTime(), stop, markBeans, record.getUuid());
			}
		}
		
		LOG.info("search manual record is end---------------");
		
		return resultBeanList;
	}

	/**
	 * 根据RecordSearchBean 中传入的一批IP设备及标记值，查找出手工录像记录的列表
	 * @param searchBean
	 * @return
	 */
	private List<VideoManualRecord> getRecordList(RecordSearchBean searchBean, List<Integer> types) {
		
		if (searchBean == null)
			return null;
		
		List<RecordSearchDeviceInfoBean> deviceInfoList = searchBean.getDeviceInfoList();
		if (deviceInfoList == null || deviceInfoList.size() == 0)
			return null;
		
		List<VideoManualRecord> recordList = new ArrayList<VideoManualRecord>();
		
		Date startTime = NvrBeanTransUtil.transTimeInfoToDate(searchBean.getStartTime());
		
		Date stopTime = NvrBeanTransUtil.transTimeInfoToDate(searchBean.getStopTime());
		
		// 检索条件的 开始时间 >= 结束时间，则检索条件非法
		if (!startTime.before(stopTime))
			return null;
		
//		String types = getManualRecordTypeFromSearchType(searchBean.getType());
		
		for (Integer type:types){
			for (RecordSearchDeviceInfoBean deviceInfo:deviceInfoList){
				
				List<VideoManualRecord> deviceList = manualRecordDao.getRecordByDevice(deviceInfo.getVideoDeviceId(), 
						deviceInfo.getVideoDeviceChannelIndex(), searchBean.getUserId(), deviceInfo.getMarks(), 
						startTime, stopTime, type);
				
				if (deviceList !=null && deviceList.size() != 0){
					
					for (VideoManualRecord record:deviceList){
						TimeIntersection recordTime = new TimeIntersection(record.getStartTime(),
									record.getStopTime());
						TimeIntersection searchTime = new TimeIntersection(startTime, stopTime);
						
						TimeIntersection realTime = recordTime.countIntersection(searchTime);
						
						if (realTime != null && realTime.isValid()){
							record.setStartTime(realTime.getStartTime());
							record.setStopTime(realTime.getStopTime());
						}
					}
					
					recordList.addAll(deviceList);
				}
			}
		}
		
		return recordList;
	}

//	private String getManualRecordTypeFromSearchType(int type) {
//		
//		StringBuilder types = new StringBuilder();
//		
//		if ( (type | RecordSearchService.TYPE_MANUAL_RECORD) != 0){
//			types.append("0");
//		}
//	}

	@Override
	public boolean isRecording(String deviceId, int channelIndex) {
		VideoManualRecord recording = manualRecordDao.getRecodingDevice(deviceId, channelIndex);
		
		if (recording == null){
			return false;
		} 
		
		return true;
	}

	@Override
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	public void stopRecordingOfIpchannel(String nvrIp, int ipchannel) {
		
		VideoManualRecord recording = manualRecordDao.getRecodingByIpchannel(nvrIp, ipchannel);
		
		// 没有和 该ip通道关联的正在录像设备
		if (recording == null){
			return;
		}
		
		recording.setIsRecoding(false);
		recording.setStopTime(dvrService.getCurrentNvrTime(nvrIp));
		
		manualRecordDao.update(recording);
	}

	@Override
	public List<RecordSearchResultBean> searchRecordByMark(String mark) {
		
		List<RecordSearchResultBean> resultBeanList = new ArrayList<RecordSearchResultBean>();
		
		List<VideoManualRecord> recordList = manualRecordDao.getRecordByMark(mark);
		
		Map<String, RecordSearchResultBean> resultMap = new HashMap<String, RecordSearchResultBean>();
		
		if (recordList != null && recordList.size() != 0){
			for (VideoManualRecord record : recordList){
				NvrDeviceInfo nvr = record.getIpChannel().getNvrDevice();
				String nvrIp = nvr.getIp();
				int ipchannelIndex = record.getIpChannel().getNvrChannel();
				RecordSearchResultBean tempBean = resultMap.get(nvrIp + "_" + ipchannelIndex);
				if (tempBean == null){
					tempBean = new RecordSearchResultBean();
					tempBean.setIp(nvrIp);
					tempBean.setPort(nvr.getPort());
					tempBean.setUsername(nvr.getUsername());
					tempBean.setPasswd(nvr.getPasswd());
					tempBean.setIpchannel(ipchannelIndex);
					resultMap.put(nvrIp + "_" + ipchannelIndex, tempBean);
					resultBeanList.add(tempBean);
				}
				
				// 若record的 停止时间为null,表示record正在录像，则设置当前nvr时间为停止时间
				Date stop = dvrService.getCurrentNvrTime(nvrIp);
				if (record.getStopTime() != null)
					stop = record.getStopTime();
				
				List<RecordMarkBean> markBeans = new ArrayList<RecordMarkBean>();
				
				for (RecordMarkInfo markInfo:record.getRecordMarks()){
					markBeans.add(NvrBeanTransUtil.transMarkInfoToMarkBean(markInfo));
				}
				tempBean.addTimePeriod(record.getDeviceId(), record.getDeviceChannel(), 
						record.getStartTime(), stop, markBeans, record.getUuid());
			}
		}
		
		LOG.info("duty check record search is end---------------");
		
		return resultBeanList;
	}

	@Override
	public VideoManualRecord getRecordByUuid(String recordUuid) {
		
		return manualRecordDao.getRecordByUuid(recordUuid);
	}

	@Override
	public List<VideoManualRecord> getRecordingDevice() {
		
		return manualRecordDao.getRecodingDevice();
	}

}
